﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using Microsoft.Phone.Marketplace;
using RedBit.OAuthLibrary;
using TradeMeSDK;

namespace TradeMo
{
    public class ListingViewModel : BaseViewModel
    {
        private ListedItemDetail _listing;
        public ListedItemDetail Listing
        {
            get { return _listing; }
            set
            {
                _listing = value;

                if (_listing.PictureHref == null)
                {
                    if (MainPhoto != null)
                        _listing.PictureHref = MainPhoto.Value.Thumbnail;
                }
                NotifyAll();
            }
        }

        private void NotifyAll()
        {
            NotifyPropertyChanged(new[]
					{
						"Listing", "Picture", "LargePicture", "FullPicture",
						"TitleBids", "AuctionCloses",
						"WatchCountText", "ViewCountText", "BidCountText",
						"BuyNowDescription", 
						"NoReserve", "IsReserveMet", "IsMember",
						"IsDealer", "IsAgency", "IsOpen", "ShowSaveToWatchList",
						"HasAttributes",
						"ShowLoginButton", "ShowBidGrid",
						"SellerLocation", "MemberSince", "PossitiveFeedback",
						"IsOnWatchList"
					});

        }

        private bool _isLoading;
        public bool IsLoading
        {
            get { return _isLoading; }
            set { _isLoading = value; NotifyPropertyChanged("IsLoading"); }
        }

        private int _listingId;
        public int ListingId
        {
            get { return _listingId; }
            set
            {
                _listingId = value;
                LoadListing();
            }
        }

        public bool IsOpen
        {
            get
            {
                if (Listing == null) return false;
                return Listing.EndDate >= DateTime.UtcNow;
            }
        }

        public bool ShowSaveToWatchList
        {
            get
            {
                return IsOpen && !IsOnWatchList;
            }
        }

        public bool ShowLoginButton
        {
            get
            {
                return !TradeMe.IsLoggedIn && IsOpen;
            }
        }

        public bool HasAttributes
        {
            get
            {
                if (Listing == null) return false;
                if (Listing.Attributes == null) return false;
                return Listing.Attributes.Count > 0;
            }
        }

        public bool ShowBidGrid
        {
            get
            {
                return TradeMe.IsLoggedIn && IsOpen;
            }
        }

        private void LoadListing()
        {
            if (_listingId == 0) return;
            IsLoading = true;
            if (App.TradeMe.IsLoggedIn)
                App.TradeMe.Search.LoggedOnListing(_listingId, OnListingLoaded);
            else
                App.TradeMe.Search.Listing(_listingId, OnListingLoaded);
        }

        private void OnListingLoaded(BaseEventArgs<ListedItemDetail> result)
        {
            IsLoading = false;
            if (result.IsError)
            {
                MessageBox.Show("Bugger: Unable to access listing");
                return;
            }
            Listing = result.Response;

            BidAmount = Listing.MaxBidAmount != 0 ? Listing.MaxBidAmount + 1 : Listing.StartPrice;

            App.Model.Recent.AddRecentlyViewed(Listing);

            Bids.Clear();
            Question = "";
            if (Listing.Bids != null)
            {
                foreach (var bid in Listing.Bids.List)
                    Bids.Add(new BidViewModel { Bid = bid });
            }
            Questions.Clear();
            if (Listing.Questions != null)
            {
                foreach (var question in Listing.Questions.List)
                    Questions.Add(new QuestionViewModel { Question = question });
            }

            bool enableSelection = IsOpen && App.TradeMe.IsLoggedIn;
            ShippingOptions.Clear();
            //ShippingOptions.Add(Listing.AllowsPickups != "Forbids"
            //                        ? new ShippingViewModel("Seller allows pickups")
            //                        : new ShippingViewModel("Seller does not allow pickups"));
            if (Listing.ShippingOptions != null)
            {
                foreach (var shippingOption in
                    Listing.ShippingOptions.Where(shippingOption => shippingOption.Type != "None"))
                {
                    var shipping = new ShippingViewModel { ShippingOption = shippingOption, EnableSelection = enableSelection };
                    if (string.IsNullOrEmpty(shipping.ShippingOption.Method))
                    {
                        switch (shipping.ShippingOption.Type)
                        {
                            case "0":
                                shipping.ShippingOption.Method = "None";
                                break;
                            case "1":
                                shipping.ShippingOption.Method = "Undecided";
                                break;
                            case "2":
                                shipping.ShippingOption.Method = "Pickup";
                                break;
                            case "3":
                                shipping.ShippingOption.Method = "Free";
                                break;
                            default:
                                shipping.ShippingOption.Method = "Unknown";
                                break;
                        }
                    }
                    ShippingOptions.Add(shipping);
                }
            }

            // Category="0002-0352-9333-9391-"
            // CategoryPath="/Computers/Apple/iPads/Cases-protectors"

            Breadcrumb.Clear();
            var catlist = App.TradeMe.CategoryTree(Listing.Category);
            foreach (var category in catlist)
                Breadcrumb.Add(category);

            View.GotoState("LoadedState", true);

            if (!App.IsTrial) return;

            App.ListingCount++;
            if (((App.ListingCount % 5) != 4) &&
                (App.ListingCount < 25))
                return;

            ShowingTrial = true;
            View.GotoState("TrialModeState", true);
        }

        public TradeMeRepository TradeMe
        {
            get { return App.TradeMe; }
        }

        private ObservableCollection<BidViewModel> _bids;
        public ObservableCollection<BidViewModel> Bids
        {
            get { return _bids ?? (_bids = new ObservableCollection<BidViewModel>()); }
        }

        private ObservableCollection<QuestionViewModel> _questions;
        public ObservableCollection<QuestionViewModel> Questions
        {
            get { return _questions ?? (_questions = new ObservableCollection<QuestionViewModel>()); }
        }

        private ObservableCollection<ShippingViewModel> _shippingOptions;
        public ObservableCollection<ShippingViewModel> ShippingOptions
        {
            get { return _shippingOptions ?? (_shippingOptions = new ObservableCollection<ShippingViewModel>()); }
        }

        private ObservableCollection<Category> _breadcrumb;
        public ObservableCollection<Category> Breadcrumb
        {
            get { return _breadcrumb ?? (_breadcrumb = new ObservableCollection<Category>()); }
        }

        public string Picture
        {
            get
            {
                if (Listing == null) return null;
                Photo photo = MainPhoto;
                return photo == null ? Listing.PictureHref : photo.Value.Large;
            }
        }

        public string LargePicture
        {
            get
            {
                if (Listing == null) return null;

                Photo photo = SelectedPhoto ?? MainPhoto;
                return photo == null ? Listing.PictureHref : photo.Value.Large;
            }
        }

        public string FullPicture
        {
            get
            {
                if (Listing == null) return null;

                Photo photo = SelectedPhoto ?? MainPhoto;
                return photo == null ? Listing.PictureHref : photo.Value.FullSize;
            }
        }

        private Photo MainPhoto
        {
            get
            {
                if (Listing == null) return null;
                Photo photo = null;
                if (Listing.Photos != null)
                    photo = Listing.Photos.FirstOrDefault(p => ((p.Value != null) && (p.Value.PhotoId == Listing.PhotoId)));
                return photo;
            }
        }

        private Photo _selectedPhoto;
        public Photo SelectedPhoto
        {
            get { return _selectedPhoto; }
            set
            {
                _selectedPhoto = value;
                NotifyPropertyChanged("LargePicture");
                NotifyPropertyChanged("FullPicture");
            }
        }

        public string TitleBids
        {
            get
            {
                if (Listing == null) return "";
                decimal price = 0;
                string reason = "";
                if (Listing.MaxBidAmount > 0)
                {
                    reason = "Current bid: ";
                    price = Listing.MaxBidAmount;
                }
                else if (!string.IsNullOrEmpty(Listing.PriceDisplay))
                {
                    return Listing.PriceDisplay;
                }
                else if (Listing.StartPrice > 0)
                {
                    reason = "Start price: ";
                    price = Listing.StartPrice;
                }
                if (price == 0) return "";

                return reason + string.Format("$ {0:0.00}", price);
            }
        }

        public string BuyNowDescription
        {
            get
            {
                if ((Listing == null) || (!Listing.HasBuyNow)) return "";
                return string.Format("Buy Now for ${0:0.00}", Listing.BuyNowPrice);
            }
        }

        private decimal _bidAmount;
        public decimal BidAmount
        {
            get { return _bidAmount; }
            set { _bidAmount = value; NotifyPropertyChanged("BidAmount"); }
        }

        private bool _autoBid;
        public bool AutoBid
        {
            get { return _autoBid; }
            set { _autoBid = value; NotifyPropertyChanged("AutoBid"); }
        }

        public string AuctionCloses
        {
            get
            {
                if (Listing == null) return "";

                TimeSpan span = Listing.EndDate - DateTime.UtcNow;

                if (span.TotalHours > 24)
                    return "Closes on " + Listing.EndDate.ToLocalTime().ToString("ddd d MMMM, hh:mm tt");
                if (span.TotalHours > 1)
                    return "Closes at " + Listing.EndDate.ToLocalTime().ToString("t");
                if (span.TotalMinutes > 1)
                    return "Closes in " + (int)span.TotalMinutes + " mins";
                if (span.TotalSeconds > 1)
                    return "Closes in " + (int)span.TotalSeconds + " seconds";
                return "Closed";
            }
        }

        public string WatchCountText
        {
            get
            {
                if (Listing == null) return "";
                if (Listing.BidderAndWatchers == 0) return "";
                return string.Format("{0} Watchers", Listing.BidderAndWatchers);
            }
        }
        public string ViewCountText
        {
            get
            {
                if (Listing == null) return "";
                if (Listing.ViewCount == 0) return "";
                return string.Format("{0} Views", Listing.ViewCount);
            }
        }

        public string BidCountText
        {
            get
            {
                if (Listing == null) return "";
                if (Listing.BidCount == 0) return "";
                return string.Format("{0} bids", Listing.BidCount);
            }
        }

        public bool NoReserve
        {
            get
            {
                if (Listing == null) return false;
                return (!Listing.HasReserve);
            }
        }

        public bool IsReserveMet
        {
            get
            {
                if (Listing == null) return false;
                return Listing.HasReserve && Listing.IsReserveMet;
            }
        }

        public bool IsAgency
        {
            get
            {
                if (Listing == null) return false;
                return Listing.Agency != null;
            }
        }

        public bool IsDealer
        {
            get
            {
                if (Listing == null) return false;
                return Listing.Dealership != null;
            }
        }

        public bool IsMember
        {
            get
            {
                if (Listing == null) return false;
                return Listing.Member != null;
            }
        }

        public string SellerLocation
        {
            get
            {
                if (Listing == null) return "";
                return string.Format("{0}, {1}", Listing.Suburb ?? "", Listing.Region ?? "");
            }
        }

        public string UniquePositive
        {
            get
            {
                if ((Listing == null) || (Listing.Member == null)) return "";
                return string.Format("({0})", Listing.Member.UniquePositive);
            }
        }

        public string MemberSince
        {
            get
            {
                if ((Listing == null) || (Listing.Member == null)) return "";
                return "Member since " + Listing.Member.DateJoined.ToString("MMMM yyyy ");
            }
        }

        public string PossitiveFeedback
        {
            get
            {
                if ((Listing == null) || (Listing.Member == null)) return "";
                if (Listing.Member.FeedbackCount == 0) return "";
                if (Listing.Member.UniquePositive == 0) return "";
                return string.Format("{0:0%} possitive feedback", Listing.Member.UniquePositive / Listing.Member.FeedbackCount);
            }
        }

        public bool IsOnWatchList
        {
            get
            {
                if (Listing == null) return false;
                if (Listing.IsOnWatchList) return true;
                //if (App.TradeMe.IsLoggedIn)

                return false;
            }
            set
            {
                if (Listing == null) return;
                Listing.IsOnWatchList = true;
                NotifyPropertyChanged("IsOnWatchList");
            }
        }

        public bool IsJob
        {
            get
            {
                if (Listing == null) return false;
                if (string.IsNullOrEmpty(Listing.Category)) return false;
                return Listing.Category.StartsWith("5000-");
            }
        }
        public bool IsProperty
        {
            get
            {
                if (Listing == null) return false;
                if (string.IsNullOrEmpty(Listing.Category)) return false;
                return Listing.Category.StartsWith("0350-");
            }
        }
        public bool IsMotor
        {
            get
            {
                if (Listing == null) return false;
                if (string.IsNullOrEmpty(Listing.Category)) return false;
                return Listing.Category.StartsWith("0001-");
            }
        }

        public void Refresh()
        {
            LoadListing();
        }

        public bool ShowingTrial { get; set; }
        public bool AskingQuestion { get; set; }
        private string _question;
        public string Question
        {
            get { return _question; }
            set { _question = value; NotifyPropertyChanged("Question"); }
        }

        public void SubmitQuestion()
        {
            if (string.IsNullOrEmpty(Question))
                return;

            App.TradeMe.MyTradeMe.PostComment(Listing.ListingId, Question, result =>
                    {
                        if (result.IsError)
                        {
                            MessageBox.Show("Unable to post question\r\n" + result.ErrorMessage);
                            return;
                        }
                        Questions.Add(new QuestionViewModel { Question = result.Response });
                    });
        }

        public void UpdateWatchList()
        {
            if (!App.TradeMe.IsLoggedIn)
            {
                MessageBox.Show("You must be logged in to add to your watchlist");
                return;
            }

            App.TradeMe.MyTradeMe.MyTradeMeAddToWatchList(Listing.ListingId, result =>
                    {
                        if (result.IsError)
                        {
                            MessageBox.Show("Bugger: Unable to add to watchlist");
                            return;
                        }
                        if (!result.Response.Success)
                        {
                            MessageBox.Show(string.Format("Unable to add to Watchlist ({0})", result.Response.Description));
                            return;
                        }

                        IsOnWatchList = true;
                        MessageBox.Show("Added to watchlist");
                        NotifyPropertyChanged("Lsting");
                    });
        }

        private int SelectedShippingOption
        {
            get
            {
                foreach (var option in ShippingOptions)
                {
                    if (option.IsSelected)
                        return option.ShippingOption.ShippingId;
                }
                return 0;
            }
        }

        public IListingView View { get; set; }

        public void Bid()
        {
            if (Listing == null) return;
            if (DateTime.UtcNow >= Listing.EndDate)
            {
                MessageBox.Show("Auction has ended");
                return;
            }


            if ((Listing.MaxBidAmount > 0) && (BidAmount <= Listing.MaxBidAmount))
            {
                MessageBox.Show(string.Format("You must bid more than the previous bid amount of ${0:0.00}",
                    Listing.MaxBidAmount));
                return;
            }

            if ((Listing.StartPrice > 0) && (BidAmount < Listing.StartPrice))
            {
                MessageBox.Show(string.Format("You must bid more than the start amount of ${0:0.00}",
                    Listing.StartPrice));
                return;
            }

            var confirm = MessageBox.Show(string.Format("bid ${0:0.00}", BidAmount),
                                            "Please confirm your bid", MessageBoxButton.OKCancel);
            if (confirm == MessageBoxResult.Cancel)
                return;

            var bidRequest = new BidRequest
                                 {
                                     Amount = BidAmount,
                                     AutoBid = AutoBid,
                                     ListingId = Listing.ListingId,
                                     ShippingOption = SelectedShippingOption
                                 };
            App.TradeMe.MyTradeMe.PlaceBid(bidRequest, result =>
                    {
                        if (result.IsError)
                        {
                            MessageBox.Show("Unable to place bid\r\n" + result.Error.Message);
                            return;
                        }

                        MessageBox.Show("Bid Placed");

                        Refresh();
                    });
        }

        /// <summary>
        /// Reloaded page.  Update anything that could have gone wrong.
        /// </summary>
        public void LoadedAgain()
        {
            bool enableSelection = IsOpen && App.TradeMe.IsLoggedIn;
            foreach (var shippingOption in ShippingOptions)
                shippingOption.EnableSelection = enableSelection;

            NotifyPropertyChanged("TradeMe");
            NotifyAll();
        }

        public void BuyNow()
        {
            var confirm = MessageBox.Show(string.Format("prive ${0:0.00}", Listing.BuyNowPrice),
                                            "Please confirm your purchase", MessageBoxButton.OKCancel);
            if (confirm == MessageBoxResult.Cancel)
                return;

            var buyNowRequest = new BuyNowRequest { ListingId = Listing.ListingId, ShippingOption = 1 };
            App.TradeMe.MyTradeMe.BuyNow(buyNowRequest, result =>
                    {
                        if (result.IsError)
                        {
                            MessageBox.Show("Unable to buy now.  Please try again later");
                            return;
                        }
                        if (result.Response.Success)
                            MessageBox.Show("Buy Now " + result.Response.Description);
                    });
        }
    }
}
